package com.xinhe.web.service;

import com.querydsl.core.BooleanBuilder;
import com.querydsl.core.QueryResults;
import com.querydsl.core.types.ExpressionUtils;
import com.querydsl.core.types.Projections;
import com.querydsl.core.types.dsl.Expressions;
import com.querydsl.jpa.impl.JPAQueryFactory;
import com.xinhe.web.common.BusinessException;
import com.xinhe.web.common.Result;
import com.xinhe.web.entity.QGoods;
import com.xinhe.web.entity.QSeckillGoods;
import com.xinhe.web.entity.QSeckillTime;
import com.xinhe.web.entity.SeckillTime;
import com.xinhe.web.reposity.SeckillGoodsRepository;
import com.xinhe.web.reposity.SeckillTimeRepository;
import com.xinhe.web.response.SeckillGoodsView;
import com.xinhe.web.response.SeckillTimeCurrentView;
import com.xinhe.web.response.SeckillTimeLatelyView;
import com.xinhe.web.util.Snowflake;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import javax.inject.Provider;
import javax.persistence.EntityManager;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.temporal.ChronoUnit;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Objects;

@Service
public class SeckillTimeService {
    @Autowired
    private SeckillTimeRepository seckillTimeRepository;
    @Autowired
    private SeckillGoodsRepository seckillGoodsRepository;
    //查询工厂
    private JPAQueryFactory queryFactory;
    @Autowired
    private Provider<EntityManager> entityManager;

    @PostConstruct
    public void init() {
        queryFactory = new JPAQueryFactory(entityManager);
    }

    public QueryResults<SeckillTime> pageSeckillTime(int pageNum, int pageSize) {
        QSeckillTime qSeckillTime = QSeckillTime.seckillTime;
        BooleanBuilder builder = new BooleanBuilder();
        //builder.and(qSeckillTime.removed.eq(0));
        return queryFactory.select(
                Projections.bean(
                        SeckillTime.class,
                        qSeckillTime.startTime,
                        qSeckillTime.endTime,
                        //qSeckillTime.remark,
                        qSeckillTime.id
                )
        ).from(qSeckillTime)
                .where(builder).offset(pageNum * pageSize).limit(pageSize).fetchResults();
    }


    @Transactional
    public Result saveSeckillTime(Long id, Date startTime, Date endTime, String remark) {
        List<SeckillTime> seckillTimes = this.seckillTimeRepository.findAll();
        if (CollectionUtils.isNotEmpty(seckillTimes)) {
            for (SeckillTime seckillTime : seckillTimes) {
                LocalTime newStartTime = startTime.toInstant().atZone(ZoneId.systemDefault()).toLocalTime();
                LocalTime newEndTime = endTime.toInstant().atZone(ZoneId.systemDefault()).toLocalTime();

                LocalTime startTime2 = seckillTime.getStartTime().toInstant().atZone(ZoneId.systemDefault()).toLocalTime();
                LocalTime endTime2 = seckillTime.getEndTime().toInstant().atZone(ZoneId.systemDefault()).toLocalTime();

                if (newStartTime.compareTo(startTime2) > 0 && newEndTime.compareTo(endTime2) < 0) {
                    throw new BusinessException(4001,"重复时间段");
                }
            }
        }
        SeckillTime seckillTime = new SeckillTime();
        seckillTime.setId(Snowflake.generateId());
        seckillTime.setStartTime(startTime);
        seckillTime.setEndTime(endTime);
        seckillTimeRepository.save(seckillTime);
        return Result.ok();
    }


    public Result<SeckillTimeCurrentView> findCurrentSeckillTime() {
        List<SeckillTime> seckillTimeList= this.seckillTimeRepository.findCurrentSeckillTime();
        if (CollectionUtils.isEmpty(seckillTimeList)) {
            return Result.ok();
        }
        SeckillTime seckillTime = seckillTimeList.get(0);
        Calendar now = Calendar.getInstance();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(seckillTime.getEndTime());
        calendar.set(1, now.get(1));
        calendar.set(2, now.get(2));
        calendar.set(5, now.get(5));
        SeckillTimeCurrentView view = new SeckillTimeCurrentView();
        BeanUtils.copyProperties(seckillTime, view);
        view.setTime(Long.valueOf(calendar.getTimeInMillis() - now.getTimeInMillis()));
        return Result.ok(view);
    }


    public Result<SeckillTimeLatelyView> findLatelySeckillTime() {
        List<SeckillTime> seckillTimeList= this.seckillTimeRepository.findCurrentSeckillTime();
        if (CollectionUtils.isEmpty(seckillTimeList)) {
            seckillTimeList = this.seckillTimeRepository.findLatelySeckillTime();
            if (CollectionUtils.isEmpty(seckillTimeList)) {
                return Result.ok();
            }
        }
        SeckillTime seckillTime = seckillTimeList.get(0);
        SeckillTimeLatelyView view = new SeckillTimeLatelyView();
        BeanUtils.copyProperties(seckillTime, view);
        LocalTime startTime = seckillTime.getStartTime().toInstant().atZone(ZoneId.systemDefault()).toLocalTime();
        LocalTime nowTime = LocalTime.now();
        if (startTime.compareTo(nowTime) > 0) {
            long between = ChronoUnit.MILLIS.between(nowTime, startTime);
            view.setTime(Long.valueOf(between));
        }
        QSeckillGoods qSeckillGoods = QSeckillGoods.seckillGoods;
        QSeckillTime qSeckillTime = QSeckillTime.seckillTime;
        QGoods qGoods = QGoods.goods;
        BooleanBuilder builder = new BooleanBuilder();
        //builder.and(qShop.removed.eq(0));
        if (!Objects.isNull(seckillTime.getId())) {
            builder.and(qSeckillGoods.seckillTimeId.eq(seckillTime.getId()));
        }
        String concatString = "-";//'%H:%i'
        String dateFormat = "%H:%i";
        List<SeckillGoodsView> seckillGoodsViews = queryFactory.select(
                Projections.bean(
                        SeckillGoodsView.class,
                        qSeckillGoods.id,
                        qGoods.id.as("goodsId"),
                        qGoods.iconPath,
                        qGoods.name,
                        qGoods.dis,
                        qGoods.price,
                        qSeckillGoods.seckillTimeId,
                        ExpressionUtils.as(
                                Expressions.stringTemplate("concat('{0}',date_format({1}, '{2}'), date_format({3}, '{4}'))",
                                        concatString,qSeckillTime.startTime, dateFormat,qSeckillTime.endTime, dateFormat),
                                "timeSlot")
                )
        ).from(qSeckillGoods)
                .leftJoin(qSeckillTime).on(qSeckillGoods.seckillTimeId.eq(qSeckillTime.id))
                .leftJoin(qGoods).on(qSeckillGoods.goodsId.eq(qGoods.id))
                .where(builder).limit(2)//设置查询两条记录
                .fetch();
        view.setSeckillGoodsViewList(seckillGoodsViews);
        return Result.ok(view);
    }

    public Result delete(Long seckillTimeId) {
        seckillTimeRepository.deleteById(seckillTimeId);
        return  Result.ok();
    }

    public Result<SeckillTime> findById(Long seckillTimeId) {
        return  Result.ok(seckillTimeRepository.findById(seckillTimeId).get());
    }
}
